5

需求

在上一篇推送,我提到了这样一个需求:

A上传一份任务文件(文件类型不限)到网站上,B看到后下载文件,按照文件里的要求完成任务之后,B要把任务完成情况汇总到一个Excel文档中,上传到网站上(此时只能上传xls格式的excel文档),然后网站在后台对这份Excel文档的数据进行处理,生成一份新的Excel文档。

所以,我写了一篇分享《node.js实现上传与下载文件》。而这次,我想针对这个需求分享下:node.js读写excel文件。

实现

思路

  • 有哪些外部模块支持读写Excel

  • 引入模块

  • 编写业务逻辑函数

支持读写Excel的node.js模块

上npm搜索过,发现支持读写excel文件的模块有很多,但是都各有缺陷,有些仅支持xls/xlsx的一种格式,有些仅支持读取数据,有些仅支持导出文件。例如:

  • node-xlsx: 基于Node.js解析excel文件数据及生成excel文件,仅支持xlsx格式文件;

  • excel-parser: 基于Node.js解析excel文件数据,支持xls及xlsx格式文件;

  • excel-export : 基于Node.js将数据生成导出excel文件,生成文件格式为xlsx;

  • node-xlrd: 基于node.js从excel文件中提取数据,仅支持xls格式文件。

在我的项目中,我使用的是noe-xlrd模块及excel-export模块,用于提取上传上来的excel文件里的数据,以及生成新的excel文件。

引入模块

编辑项目工程里的package.json文件:

{
  "name": "appname",
  "virsion": "0.0.1",
  "dependencies": {
    "express": "~4.8.8",
    "node-xlrd": "0.2.4",
    "excel-export": "0.4.1"
  }
}

执行node命令安装模块

npm install

编写业务逻辑函数

1.解析excel文件数据

var xl = require('node-xlrd');

exports.read = function(req, res, next){
    var path = 'test.xls';
    var datas = [];

    xl.open(path, function(err,bk){
        if(err) {console.log(err.name, err.message); return;}
        
        var shtCount = bk.sheet.count;
        for(var sIdx = 0; sIdx < shtCount; sIdx++ ){
            console.log('sheet "%d" ', sIdx);
            console.log('  check loaded : %s', bk.sheet.loaded(sIdx) );
            var sht = bk.sheets[sIdx],
                rCount = sht.row.count,
                cCount = sht.column.count;
            console.log('  name = %s; index = %d; rowCount = %d; columnCount = %d', sht.name, sIdx, rCount, cCount);
            for(var rIdx = 0; rIdx < rCount; rIdx++){    // rIdx:行数;cIdx:列数
                var data = [];
                for(var cIdx = 0; cIdx < cCount; cIdx++){
                    try{
                        data[cIdx] = sht.cell(rIdx,cIdx);
                        console.log('  cell : row = %d, col = %d, value = "%s"', rIdx, cIdx, sht.cell(rIdx,cIdx));
                    }catch(e){
                        console.log(e.message);
                    }
                }
                datas[rIdx] = data;
            }
        }

        req.datas = datas;
    });
};

解析出来的数据有不同的数据类型:string、number。可以用 typeof sht.cell(rIdx,cIdx) 检测数据类型。

2.将处理后的数据生成新的excel文件

var excelPort = require('excel-export');
exports.write = function(req, res, next){
    var datas = req.datas;
    var conf = {};
    var filename = 'filename';  //只支持字母和数字命名

    
    conf.cols = [
       {caption:'名称', type:'string', width:20},
       {caption:'简介', type:'string', width:40},
       {caption:'报酬', type:'string', width:20},
       {caption:'时间', type:'date', width:40},
       {caption:'人员', type:'string', width:30},
       {caption:'编号', type:'string', width:30},
       {caption:'金额', type:'number', width:30},
       {caption:'手机号', type:'string', width:30}
    ];

    
    var array = [];
    array[0] = [
        datas[0][0],
          datas[0][1],
          datas[0][2],
          datas[0][3],
          datas[0][4],
          datas[0][5],
          datas[0][6],
          datas[0][7]
    ];


    conf.rows = array[0];
    var result = excelPort.execute(conf);

    var random = Math.floor(Math.random()*10000+0);

    var uploadDir = 'public/upload/pay/';
    var filePath = uploadDir + filename + random + ".xlsx";

    fs.writeFile(filePath, result, 'binary',function(err){
        if(err){
            console.log(err);
        }
    });
}

caption设置首行各单元格内容,type设置的是每一列的数据类型,width设置单元格大小。

rows 赋值的是每一行的数据,每个数据都要与所在列所设置的数据格式一致,否则会报错,生成后的表格该单元格会显示NaN。

总结

在读取解析完excel文件里的数据后,一般要根据项目需求对数据进行处理。进行数据处理时,要格外注意所解析到的数据的数据类型,以及要生成新的表格时,处理后的数据的数据类型是否符合所设置的数据类型。否则,bug不断....


small2
1.5k 声望95 粉丝

海潮迷